function AdaptID_v1_1(protocolListFileName)
%AdaptID_v1_1: Run the Individual Adaptation experiment
%           AdaptID_v1_1(protocolListFileName)
%
%   AdaptID_v1_1(protocolListFileName) initializes the Individual
%   Adaptation fMRI experiment. This experiment aims to investigate the
%   effect of stimulus history on the current evoked response, when stimuli
%   on serial position -1 to -N are manipulated in a counterbalanced way.
%
%   IMPORTANT!
%   It is recommended that this file is located on ./Experiment/AdaptID_v1_1.m
%   The program will create the ./Data directory for saving the data
%
%
%   Inputs
%   -------
%   [protocolListFileName]: path to a file that should contain a
%           description of the protocols to be used. If nothing is entered,
%           the file ./Config/ProtocolList.cfg will be used
%
%
%   Outputs
%   -------
%   ./Data/[expType]/[protocol]/[subjID]/[subjID]-[protocol]-[iteration].mat
%           this file will store all experimental info, experiment
%           parameters, stimuli used, and data collected
%
%   Examples
%   -------
%    i) AdaptID_v1_1('./protocols.txt')
%   ii) AdaptID_v1_1
%
%   _______________________________________________
%   by Marcelo G Mattar (09/04/2012)
%   mattar@sas.upenn.edu


%% PARAMETERS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% General
expInfo.expType = 'fMRI'; % Experiment type. Enter "fMRI" or "Behavioal" to specify the directory where the data will be saved

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%% DIRECTORY INFORMATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Get directory information
% IMPORTANT! The Data and StimSet directories should be on the same level as the Experiment directory!
expInfo.dir.currDir = pwd;  % Current directory path
expInfo.dir.baseDir = fileparts(which(mfilename)); % Code directory path.
i = max(strfind(expInfo.dir.baseDir, '/'));
expInfo.dir.stimDir = sprintf('%sStimSet', expInfo.dir.baseDir(1:i)); % StimSet directory path
expInfo.dir.dataDir = sprintf('%sData/%s', expInfo.dir.baseDir(1:i), expInfo.expType); % Data directory path
expInfo.dir.configDir = sprintf('%s/Config', expInfo.dir.baseDir); % Configuration file path.

% Create ./Data directory in case it doesn't exist yet
if ~exist(expInfo.dir.dataDir, 'dir')
	mkdir(expInfo.dir.dataDir);
end

% Dynamically add the program code to the path if it isn't already on it.
if isempty(strfind(path, expInfo.dir.baseDir))
	fprintf('- Adding Experiment directory dynamically to the path...');
	addpath(RemoveSVNPaths(genpath(expInfo.dir.baseDir)), '-end');
	fprintf('Done\n');
end
if isempty(strfind(path, expInfo.dir.stimDir))
	fprintf('- Adding StimSet directory dynamically to the path...');
	addpath(RemoveSVNPaths(genpath(expInfo.dir.stimDir)), '-end');
	fprintf('Done\n');
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%% CHECK INPUTS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

if nargin < 1
    protocolListFileName = sprintf('%s/ProtocolList.cfg', expInfo.dir.configDir);
end

if ~exist(protocolListFileName,'file')
    error('You must either specify a file with the protocols to be loaded, or there should be one located in the ./config directory named ProtocolList.cfg');
end

% Check how many devices are connected
if length(GetKeyboardIndices()) == 1
    fprintf('\n***** WARNING!!! There is only one keyboard connected. *****\n');
    fprintf('***** Perhaps you forgot to re-start MATLAB after pluging in the MRI-trigger USB? *****\n');
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%% PROTOCOL INFORMATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Read the protocol list.
expInfo.protocol.protocolListFileName = protocolListFileName;
expInfo.protocol.protocolList =  ReadStructsFromText(expInfo.protocol.protocolListFileName);
expInfo.protocol.numProtocols = length(expInfo.protocol.protocolList);

% Display a list of what protocols are available and have the user select
% one by number.
while true
	fprintf('\n- Available protocols\n\n');
	
	for i = 1:expInfo.protocol.numProtocols
		fprintf('%d - %s\n', i, expInfo.protocol.protocolList(i).name);
	end
	fprintf('\n');
	
	expInfo.protocolIndex = GetInput('Choose a protocol number', 'number', 1);
	
	% If the user selected a protocol in the range of available protocols,
	% break out of the loop.  Otherwise, display the protocol list again.
	if any(expInfo.protocolIndex == 1:expInfo.protocol.numProtocols)
		break;
	else
		disp('*** Invalid protocol selected, try again.');
	end
end

% Create the path to where the protocol's data will be stored.
expInfo.dir.protocolDataDir = sprintf('%s/%s', expInfo.dir.dataDir, expInfo.protocol.protocolList(expInfo.protocolIndex).dataDirectory);

% Set the config file name for this protocol.
expInfo.protocol.configFileName = sprintf('%s/%s', expInfo.dir.configDir, expInfo.protocol.protocolList(expInfo.protocolIndex).configFile);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%% SUBJECT INFORMATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% In the data directory, we can see the list of subjects available if the
% protocol has been run before.  If it hasn't been run, then we will create
% the top level data directory, then ask the user to create a subject.
availableSubjects = {};
if exist(expInfo.dir.protocolDataDir, 'dir')
	% Get a list of available subjects.
	dirList = dir(expInfo.dir.protocolDataDir);
	
	% Skip the first two results because they are '.' and '..'.
	for i = 3:length(dirList)
		% Filter out non directory files.  We assume all directories are
		% subject directories.
		if dirList(i).isdir
			if ~strcmp(dirList(i).name, '.svn')
				availableSubjects{end+1} = dirList(i).name; % add to the list of available subjects
			end
		end
	end
else
	mkdir(expInfo.dir.protocolDataDir);
end

% Display the list of available subjects and also give an option to create
% one.
while true
	fprintf('- Subject Selection\n\n');
	
	fprintf('0 - Create a new subject\n');
	
	for i = 1:length(availableSubjects)
		fprintf('%d - %s\n', i, availableSubjects{i});
	end
	fprintf('\n');
	
	subjectIndex = GetInput('Choose a subject number', 'number', 1);
	
	if subjectIndex == 0
		% Create a new subject.
        while true
            newSubjInitials = GetInput('Enter subject initials', 'string');
            if length(newSubjInitials)==2 % Check if initials were valid
                if ismember(newSubjInitials(1),[65:90,97:122]) && ismember(newSubjInitials(2),[65:90,97:122])
                    if ~ismember(subjectId(newSubjInitials),availableSubjects)
                        newSubjID = subjectId(newSubjInitials);
                        mkdir(sprintf('%s/%s', expInfo.dir.protocolDataDir, newSubjID));
                        availableSubjects{end+1} = newSubjID; % add to the list of available subjects
                        break
                    else
                        disp(['*** This subject already exists. Try again.' sprintf('\n')]);
                        break
                    end
                else
                    disp(['*** Invalid subject initials. Enter two letters.' sprintf('\n')]);
                end
            else
                disp(['*** Invalid subject initials. Enter two letters.' sprintf('\n')]);
            end
        end
	elseif any(subjectIndex == 1:length(availableSubjects))
		% We got our subject, now setup the proper variables and get out of
		% this loop.
		expInfo.subjID = availableSubjects{subjectIndex};
		expInfo.dir.subjectDataDir = sprintf('%s/%s', expInfo.dir.protocolDataDir, ...
			expInfo.subjID);
		break;
	else
		disp(['*** Invalid subject selected. Try again.' sprintf('\n')]);
	end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%% FILENAME INFORMATION
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Find the largest iteration number in the data filenames, to prevent
% overwriting data
iter = 0;
d = dir(expInfo.dir.subjectDataDir);
for i = 3:length(d)
	s = textscan(d(i).name, '%s%s%s', 'Delimiter', '-');
	if ~isempty(s{3})
		% Get rid of the .mat part.
		n = strtok(s{3}, '.');
		
		val = str2double(n);
		if ~isnan(val) && val > iter
			iter = val;
		end
	end
end
iter = iter + 1;

expInfo.dir.saveFileName = sprintf('%s/%s-%s-%d.mat', expInfo.dir.subjectDataDir, ...
	expInfo.subjID, expInfo.protocol.protocolList(expInfo.protocolIndex).dataDirectory, iter);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%% EXECUTE EXPERIMENT
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Store the date/time when the experiment starts.
expInfo.experimentTimeNow = now;
expInfo.experimentTimeDateString = datestr(expInfo.experimentTimeNow);

% Display relevant information
display(sprintf('\nSaving directory: %s', expInfo.dir.subjectDataDir))
display(sprintf('Filename: %s', expInfo.dir.saveFileName))

% Now we can execute the driver associated with this protocol.
driverCommand = sprintf('[params data stimSet] = %s(expInfo);', expInfo.protocol.protocolList(expInfo.protocolIndex).driver);
eval(driverCommand);

% Save the experimental data 'params' along with the experimental setup
% data 'exp'.
save(expInfo.dir.saveFileName, 'expInfo', 'params', 'data', 'stimSet');
fprintf('\n- Data saved to %s\n\n', expInfo.dir.saveFileName);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%







%% AUXILIARY FUNCTIONS
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function id = subjectId(initials)
    % SUBJECTID  create an Aguirre lab subject identifier
    %    id = subjectid(initials) where initials is 'AZ' and the current date
    %    is 25 December 2008 returns the string 'A122508Z'
    %
    % 2007 ddrucker@psych.upenn.edu

    initials=strtrim(initials);
    if length(initials) ~= 2
        error('Expected two letters for initials');
    end

    id = upper([initials(1) datestr(now,'mmddyy') initials(2)]);
    return



    
function data = GetInput(inputString, inputType, inputDims)
% data = GetInput(inputString, [inputType], [inputDims])
%
% Description:
% Gets user input from the command line.
%
% Required Input:
% inputString (string) - The query that will be shown to the users.
%    Example: 'Enter your selection'.
%
% Optional Inputs:
% inputType (string) - Can be either 'number' or 'string'.  Defaults to
%    'number'.
% inputDims (integer vector) - For an inputType of 'string', this represents the
%    limits on the size of the input string.  Defaults to [1,256].  For
%    'number', this represents the number of elements in the inputted vector.
%    Defaults to 1.  This value can also be -1, which implies that any input
%    is accepted.
%
% Output:
% data (string|vector) - The inputted string or vector.
%
% Example:
% data = GetInput('Please Insert a Number', 'number', 2);
% Please Insert a Number: <user input goes here>

if nargin < 1 || nargin > 3
    error('Usage: data = GetInput(inputString, inputType, inputDims)');
end

% Setup some defaults.
if nargin == 1
    inputType = 'number';
    inputDims = 1;
end

% Make sure inputType is valid.
if ~any(strcmp(inputType, {'number', 'string'}))
    error('*** Invalid inputType, must choose ''number'' or ''string''');
end

% Make sure the input dimensions are valid
switch inputType
    case 'number'
        if ~exist('inputDims', 'var')
            inputDims = 1;
        end
        
        % Make sure inputDims is a single scalar.
        if ~isscalar(inputDims)
            error('*** Invalid inputDims, must be a single scalar for type ''number''');
        end
        
    case 'string'
        % Setup the default string length if it wasn't specified.
        if nargin < 3
            inputDims = [1, 256];
        else
            % Make sure inputDims is a 1x2 matrix.
            if ~all(size(inputDims) == 1:2)
                error('*** Invalid inputDims, must be of form [x,y] for type ''string''');
            end
        end
end

% Grab the data from the user.  Loop until the data is valid.
inputString = [inputString, ': '];
keepLooping = true;
while keepLooping
    if strcmp(inputType, 'number')
        data = str2num(input(inputString, 's')); %#ok<ST2NM>
        
        % inputDims of -1 implies we'll take anyingthing as input.
        if inputDims == -1
            keepLooping = false;
        else
            if numel(data) == inputDims
                keepLooping = false;
            else
                beep;
                fprintf('*** Invalid entry, must be a vector of length %d.\n', inputDims);
            end
        end
    else
        data = input(inputString, 's');
        
        lenData = length(data);
        if lenData >= inputDims(1) && lenData <= inputDims(2)
            keepLooping = false;
        else
            beep;
            fprintf('*** Invalid entry, must be a string >= %d and <= %d in length\n', inputDims(1), inputDims(2));
        end
    end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
